package com.bwie.rent.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bwie.common.utils.CheckObjectNull;
import com.bwie.common.utils.R;
import com.bwie.rent.dao.PayDao;
import com.bwie.rent.entity.*;
import com.bwie.rent.feign.AssistFeign;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.common.utils.PageUtils;
import com.bwie.common.utils.Query;

import com.bwie.rent.dao.RentDao;
import com.bwie.rent.service.RentService;


@Service("rentService")
public class RentServiceImpl extends ServiceImpl<RentDao, RentEntity> implements RentService {

    @Autowired
    RestHighLevelClient client;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    RentDao rentDao;

    @Autowired
    PayDao payDao;

    @Autowired
    AssistFeign assistFeign;



    /**
     * 列表查询
     * */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
            String key = (String) params.get("key");

            QueryWrapper<RentEntity> wrapper = new QueryWrapper<>();
            if (StringUtils.isNotBlank(key))
                wrapper.like("house_title",key);
            IPage<RentEntity> page = this.page(
                    new Query<RentEntity>().getPage(params),
                    wrapper
            );
            return new PageUtils(page);

    }

    /**
     * es列表查询
     * */
    @Override
    public PageUtils findEsList(Map<String, Object> params, EsHouseRent esHouseRent) throws IOException {

        String page = (String) params.get("page");
        String limit = (String) params.get("limit");

        if("1".equals(page) && "2".equals(limit) && CheckObjectNull.checkObjAllFieldsIsNull(esHouseRent)){
            String houselist = stringRedisTemplate.opsForValue().get("houselist");
            if (StringUtils.isNotBlank(houselist)){
                PageUtils pageUtils = JSON.parseObject(houselist, new TypeReference<PageUtils>() {
                });
                System.out.println("从redis取值");
                return pageUtils;
            }else {
                IPage<RentEntity> pages = this.page(
                        new Query<RentEntity>().getPage(params),
                        new QueryWrapper<>()
                );
                PageUtils pageUtils = new PageUtils(pages);
                String s = JSON.toJSONString(pageUtils);
                stringRedisTemplate.opsForValue().set("houselist", s);
                System.out.println("存入redis");
                return pageUtils;
            }
        }

        //构建查询条件
        SearchRequest searchRequest = new SearchRequest("house_rent");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        if (StringUtils.isNotBlank(esHouseRent.getTitle()) && esHouseRent.getTitle()!=null)
            boolQueryBuilder.must(QueryBuilders.matchQuery("houseTitle", esHouseRent.getTitle()));

        if (StringUtils.isNotBlank(esHouseRent.getAddr()) && esHouseRent.getAddr()!=null)
            boolQueryBuilder.must(QueryBuilders.termQuery("houseRegionid", esHouseRent.getAddr()));

        if (esHouseRent.getType()!=null)
            boolQueryBuilder.must(QueryBuilders.termQuery("houseType", esHouseRent.getType()));

        if (esHouseRent.getPriceStatus()!=null){
                /*
                租金范围状态
                1:<=500元 2:500-1000元 3:1000-1500元
                4:1500-2000元 5:2000-2500元 6:2500-3000元
                */
            switch (esHouseRent.getPriceStatus()){
                case 1:{boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").lte(500));}break;
                case 2:{boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").gte(500).lte(1000));}break;
                case 3:{boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").gte(1000).lte(1500));}break;
                case 4:{boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").gte(1500).lte(2000));}break;
                case 5:{boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").gte(2000).lte(2500));}break;
                case 6:{boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").gte(2500).lte(3000));}break;
                default:System.out.println("都不满足");break;
            }
        }

        if (esHouseRent.getMinPrice()!=null)
            boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").gte(esHouseRent.getMinPrice()));


        if (esHouseRent.getMaxPrice()!=null)
            boolQueryBuilder.must(QueryBuilders.rangeQuery("housePrice").lte(esHouseRent.getMaxPrice()));


        if (StringUtils.isNotBlank(esHouseRent.getSize()))
            boolQueryBuilder.must(QueryBuilders.termQuery("houseSize.keyword",esHouseRent.getSize()));


        if (StringUtils.isNotBlank(esHouseRent.getDirection()))
            boolQueryBuilder.must(QueryBuilders.termQuery("houseDirection", esHouseRent.getDirection()));

        searchSourceBuilder.query(boolQueryBuilder);
        searchSourceBuilder.from((Integer.parseInt(page)-1)*Integer.parseInt(limit));
        searchSourceBuilder.size(Integer.parseInt(limit));


        HighlightBuilder highlightBuilder = new HighlightBuilder();
        HighlightBuilder.Field highlightTitle =
                new HighlightBuilder.Field("houseTitle");
        highlightTitle.highlighterType("unified");
        highlightBuilder.preTags("<span style=\"color: red\">");
        highlightBuilder.postTags("</span>");
        highlightBuilder.field(highlightTitle);
        HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
        highlightBuilder.field(highlightUser);
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = search.getHits();


        TotalHits totalHits = hits.getTotalHits();
// the total number of hits, must be interpreted in the context of totalHits.relation
        long numHits = totalHits.value;
// whether the number of hits is accurate (EQUAL_TO) or a lower bound of the total (GREATER_THAN_OR_EQUAL_TO)
        TotalHits.Relation relation = totalHits.relation;
        float maxScore = hits.getMaxScore();

        ArrayList<EsRentEntity> esRentEntities = new ArrayList<>();

        SearchHit[] searchHits = hits.getHits();
        for (SearchHit hit : searchHits) {
            // do something with the SearchHit
            String index = hit.getIndex();
            String id = hit.getId();
            float score = hit.getScore();
            String sourceAsString = hit.getSourceAsString();
            EsRentEntity esRentEntity = JSON.parseObject(sourceAsString, EsRentEntity.class);
            esRentEntity.setHouseId(Integer.parseInt(id));

            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField highlight = highlightFields.get("houseTitle");
            if (highlight!=null){
                Text[] fragments = highlight.fragments();
                String fragmentString = fragments[0].string();
                esRentEntity.setHouseTitle(fragmentString);
            }
            esRentEntities.add(esRentEntity);

        }
        return new PageUtils(esRentEntities, Integer.parseInt(numHits+""), Integer.parseInt(limit), Integer.parseInt(page));

    }

    /*TODO*/
    @Override
    public R findHouseById(String hid) {
        HouseItemEntity houseItemEntity = new HouseItemEntity();
        RentEntity rentEntity = rentDao.selectById(hid);
        BeanUtils.copyProperties(rentEntity, houseItemEntity);
        /*支付方式*/
        PayEntity payEntity = payDao.selectById(rentEntity.getHousePayType());
        houseItemEntity.setHousePayType(payEntity.getPayName());
        /*地址*/
        R addrById = assistFeign.info(Integer.parseInt(rentEntity.getHouseRegionid()));
        if (addrById.get("code").equals(0)){
            houseItemEntity.setHouseRegionid(addrById.getData(new TypeReference<AddrsTo>(){}).getAddrName());
        }
        /*图片集合*/
        R listByHouse = assistFeign.findListByHouse(rentEntity.getHouseImgid());
        if (addrById.get("code").equals(0)){
            List<ImgsTo> data = listByHouse.getData(new TypeReference<List<ImgsTo>>() {
            });
            houseItemEntity.setHouseImgid("");
            data.stream().forEach(e->{
                houseItemEntity.setHouseImgid(houseItemEntity.getHouseImgid()+","+e.getImgUrl());
            });
            houseItemEntity.setHouseImgid(houseItemEntity.getHouseImgid().substring(1));
        }
        return R.ok().put("house",houseItemEntity);
    }

}